package binary_evolution;

import misc.not_Legal_Exception;
import evolution_superclasses.Fitness_Evaluation;
import evolution_superclasses.Phenotype;

public class Binary_Fitness_Evaluation extends Fitness_Evaluation {

	public Binary_Fitness_Evaluation(int nr, boolean print) throws not_Legal_Exception {
		super(nr,print);
	}
	
	@Override
	protected double vectorAverage(Phenotype p){
		Binary_Phenotype bp = (Binary_Phenotype)p;
		int sum = 0;
		for(int i : bp.get_integers()){
			sum += i;
		}
		
		return (double)sum/bp.get_genotype().get_genSize();
	}

	@Override
	protected double distanceFromAnswer(Phenotype p) throws not_Legal_Exception {
		if(get_answer() == null){
			System.out.println("You must choose what how the target genotype will be made. \n(-1 = random)\n(1 = just ones)\n(0 = just zero)\n(2 = custom)");
			try {
				int tmp = _ih.readInt();
				switch (tmp) {
					case -1:
						createRandomSolution(p.get_genotype().get_genSize());
						break;
					case 0:
						createAllZeros(p.get_genotype().get_genSize());
						break;
					case 1:
						createAllOnes(p.get_genotype().get_genSize());
						break;
					case 2:
						createCustomSolution(p.get_genotype().get_genSize());
						break;
					default:
						System.out.println("Number must be between -1 and 2");
						return distanceFromAnswer(p);
				}
			} catch (Exception e) {
				System.out.println("Number must be between -1 and 2");
				return distanceFromAnswer(p);
			}
			if(_print){
				System.out.println("Target gen:");
				String s = "";
				Binary_Genotype bg = (Binary_Genotype)get_answer().get_genotype();
				for(boolean b :bg.get_binaryArray()){
					s += b?'1':'0';
				}
				System.out.println(s);
			}
			
		}
		int sum = 0;
		int[] test = ((Binary_Phenotype)p).get_integers();
		int[] ans = ((Binary_Phenotype)get_answer()).get_integers();
		
		for(int i = 0; i < test.length; i++){
			sum += test[i]==ans[i]?1:0;
		}
		return (double)sum/test.length;
	}

	@Override
	protected void createCustomSolution(int size){
		try {
			System.out.println("Write down either "+size+" genes, or a multiple of it. Consisting of 1s and 0s");
			String s = _ih.readString();
			if(s.length()==size || size%s.length()==0){
				Binary_Genotype bg = new Binary_Genotype(size);
				char[] ca = s.toCharArray();
				char c = ' ';
				while(size-->0){
					c = ca[size%s.length()];
					if(!Character.isDigit(c))throw new IllegalArgumentException();
					bg.editBinaryArray(size, c=='1');
				}
				set_answer(bg.generatePhenotype());
			}else{
				System.out.println("You have to write "+size+" different numbers (either 0 or 1), or a factor of "+size);
				createCustomSolution(size);
				return;
			}
		} catch (Exception e) {
			System.out.println("You have to write "+size+" different numbers (either 0 or 1), or a factor of "+size);
			createCustomSolution(size);
			return;
		}
	}

	@Override
	protected void createRandomSolution(int size) {
		Binary_Genotype bg = new Binary_Genotype(size);
		while(size-->0){
			bg.editBinaryArray(size, _rand.nextBoolean());
		}
		set_answer(bg.generatePhenotype());
	}
	
	public void createAllOnes(int size){
		Binary_Genotype bg = new Binary_Genotype(size);
		while(size-->0){
			bg.editBinaryArray(size, true);
		}
		set_answer(bg.generatePhenotype());
	}
	
	public void createAllZeros(int size){
		Binary_Genotype bg = new Binary_Genotype(size);
		while(size-->0){
			bg.editBinaryArray(size, false);
		}
		set_answer(bg.generatePhenotype());
	}

}
